<!-- src/views/product/AddProductDialog.vue -->
<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ElMessage } from 'element-plus'
import type { Product } from '@/type/product'
import { Plus } from '@element-plus/icons-vue'
import productApi from '@/api/product-api.ts'
import { fileApi } from '@/api/file-api'
import AsyncImage from '@/components/AsyncImage.vue'
import axios from 'axios'

// 定义组件属性
interface Props {
  modelValue: boolean
  editProduct?: Product | null
}

// 定义事件
interface Emits {
  (e: 'update:modelValue', value: boolean): void
  (e: 'success', product: Product): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

// 表单引用
const formRef = ref()

// 商品表单数据
const productForm = ref<Omit<Product, 'id' | 'createTime'>>({
  title: '',
  coverAddr: '',
  price: 0,
  description: '',
  rate: 0,
  detailAddr: '',
  stockpile: 0,
  specificationList: [],
})

// 文件引用
const coverFile = ref<File | null>(null)
const detailFile = ref<File | null>(null)

// 表单验证规则
const rules = {
  title: [
    { required: true, message: '请输入商品名称', trigger: 'blur' },
    { min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' },
  ],
  price: [
    { required: true, message: '请输入商品价格', trigger: 'blur' },
    { type: 'number', min: 0, message: '价格必须大于等于0', trigger: 'blur' },
  ],
  rate: [
    { required: true, message: '请输入商品评分', trigger: 'blur' },
    { type: 'number', min: 0, max: 10, message: '评分必须大于等于0', trigger: 'blur' },
  ],
  stockpile: [
    { required: true, message: '请输入商品库存', trigger: 'blur' },
    { type: 'number', min: 0, message: '库存必须大于等于0', trigger: 'blur' },
  ],
  description: [
    { required: true, message: '请输入商品描述', trigger: 'blur' },
    { min: 2, max: 1000, message: '长度在 2 到 200 个字符', trigger: 'blur' },
  ],
}

// 对话框标题
const dialogTitle = computed(() => {
  return props.editProduct ? '编辑商品' : '添加商品'
})

// 对话框可见性
const visible = computed({
  get: () => props.modelValue,
  set: (value) => emit('update:modelValue', value),
})

// 关闭对话框
const handleClose = () => {
  visible.value = false
  resetForm()
}

// 监听editProduct变化，初始化表单
watch(
  () => props.editProduct,
  (newVal: Product | null | undefined) => {
    if (newVal) {
      // 编辑模式，初始化表单数据
      productForm.value = {
        title: newVal.title || '',
        coverAddr: newVal.coverAddr || '',
        price: newVal.price || 0,
        description: newVal.description || '',
        rate: newVal.rate || 0,
        detailAddr: newVal.detailAddr || '',
        stockpile: newVal.stockpile || 0,
        specificationList: newVal.specificationList ? [...newVal.specificationList] : [],
      }
    } else {
      // 添加模式，重置表单
      resetForm()
    }
  },
)

// 重置表单
const resetForm = () => {
  productForm.value = {
    title: '',
    coverAddr: '',
    price: 0,
    description: '',
    rate: 0,
    detailAddr: '',
    stockpile: 0,
    specificationList: [],
  }
  coverFile.value = null
  detailFile.value = null
  formRef.value?.clearValidate()
}

// 处理封面图选择
const handleCoverChange = (event: Event) => {
  const target = event.target as HTMLInputElement
  if (target.files && target.files.length > 0) {
    coverFile.value = target.files[0]
  }
}

// 处理详情图选择
const handleDetailChange = (event: Event) => {
  const target = event.target as HTMLInputElement
  if (target.files && target.files.length > 0) {
    detailFile.value = target.files[0]
  }
}
const getLocalFileUrl = (file: File | null) => {
  if (!file) return ''
  return URL.createObjectURL(file)
}

// 生成随机文件名
const generateRandomFilename = (originalName: string): string => {
  const extension = getFileExtension(originalName)
  const randomString =
    Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15)
  const timestamp = Date.now()
  return `${randomString}_${timestamp}.${extension}`
}

// 获取文件后缀名
const getFileExtension = (filename: string): string => {
  return filename.slice(((filename.lastIndexOf('.') - 1) >>> 0) + 2)
}

// 上传文件并获取地址
const uploadFiles = async () => {
  // const uploadPromises = []
  const fileUploadAxios = axios.create({
    timeout: 30000, // 30秒超时
  })
  // 上传封面图
  if (coverFile.value) {
    console.log('coverFile.value.name: ', coverFile.value.name)
    // 生成随机文件名
    const randomFileName = generateRandomFilename(coverFile.value.name)
    console.log('randomFileName: ', randomFileName)

    const url = await fileApi.uploadUrl('product-cover', randomFileName)

    const extension = getFileExtension(coverFile.value.name)

    await fileUploadAxios.put(url, coverFile.value, {
      headers: {
        'Content-Type': 'image/' + extension,
      },
    })
    productForm.value.coverAddr = "product-cover:" + randomFileName
  }

  // 上传详情图
  if (detailFile.value) {
    console.log('detailFile.value.name: ', detailFile.value.name)
    // 生成随机文件名
    const randomFileName = generateRandomFilename(detailFile.value.name)
    console.log('randomFileName: ', randomFileName)

    const url = await fileApi.uploadUrl('product-detail', randomFileName)

    const extension = getFileExtension(detailFile.value.name)

    await fileUploadAxios.put(url, detailFile.value, {
      headers: {
        'Content-Type': 'image/' + extension,
      },
    })
    productForm.value.detailAddr = "product-detail:" + randomFileName
  }

}

// 提交表单
const submitForm = async () => {
  if (!formRef.value) return

  try {
    await formRef.value.validate()

    // 上传文件
    await uploadFiles()

    if (props.editProduct) {
      // 编辑模式
      const productToUpdate: Product = {
        ...props.editProduct,
        ...productForm.value,
      }
      await productApi.modify(productToUpdate)

      ElMessage.success('商品更新成功')
      emit('success', productToUpdate)
    } else {
      // 调用真实API创建商品
      const productToCreate: Omit<Product, 'id' | 'createTime'> = {
        ...productForm.value,
      }

      await productApi.create(productToCreate)

      ElMessage.success('商品添加成功')
      emit('success', productToCreate as Product)
      handleClose()
    }
  } catch (error) {
    console.error('表单验证失败:', error)
    ElMessage.error('操作失败')
  }
}

// 取消操作
const handleCancel = () => {
  handleClose()
}

// 规格相关功能
const newSpecification = ref<{
  item: string
  value: string
}>({
  item: '',
  value: '',
})

// 添加规格
const addSpecification = () => {
  if (!newSpecification.value.item || !newSpecification.value.value) {
    ElMessage.warning('请填写完整的规格项和规格值')
    return
  }

  productForm.value.specificationList?.push({
    item: newSpecification.value.item,
    value: newSpecification.value.value,
  })

  // 清空输入
  newSpecification.value = {
    item: '',
    value: '',
  }
}

// 删除规格
const removeSpecification = (index: number) => {
  productForm.value.specificationList?.splice(index, 1)
}
</script>

<template>
  <el-dialog v-model="visible" :title="dialogTitle" width="500px" :before-close="handleClose">
    <el-form
      ref="formRef"
      :model="productForm"
      :rules="rules"
      label-width="80px"
      label-position="left"
    >
      <el-form-item label="封面图" prop="coverAddr">
        <div class="file-upload-container">
          <input type="file" accept="image/*" @change="handleCoverChange" class="file-input" />
          <div class="file-upload-display">
            <div v-if="productForm.coverAddr" class="image-preview">
              <AsyncImage :image-key="productForm.coverAddr" style="width: 100%; height: 100%" />
            </div>
            <div v-else-if="coverFile" class="file-info">
              <img
                :src="getLocalFileUrl(coverFile)"
                style="width: 100%; height: 100%; object-fit: cover"
                alt="封面图预览"
              />
            </div>
            <div v-else class="upload-placeholder">
              <el-icon><Plus /></el-icon>
              <span>选择封面图</span>
            </div>
          </div>
        </div>
      </el-form-item>

      <el-form-item label="标题" prop="title">
        <el-input
          v-model="productForm.title"
          controls-position="right"
          placeholder="请输入商品名称"
        />
      </el-form-item>

      <el-form-item label="价格" prop="price">
        <el-input-number
          v-model="productForm.price"
          :min="0"
          :precision="2"
          :step="0.1"
          controls-position="right"
          style="width: 100%"
        />
      </el-form-item>

      <el-form-item label="库存" prop="stockpile">
        <el-input-number
          v-model="productForm.stockpile"
          :min="0"
          controls-position="right"
          style="width: 100%"
        />
      </el-form-item>

      <el-form-item label="描述" prop="description">
        <el-input v-model="productForm.description" type="textarea" placeholder="请输入商品描述" />
      </el-form-item>

      <el-form-item label="评分" prop="rate">
        <el-input-number
          v-model="productForm.rate"
          :min="0"
          :max="10"
          :precision="1"
          :step="0.1"
          controls-position="right"
          style="width: 100%"
        />
      </el-form-item>

      <el-form-item label="详情图" prop="detailAddr">
        <div class="file-upload-container">
          <input type="file" accept="image/*" @change="handleDetailChange" class="file-input" />
          <div class="file-upload-display">
            <div v-if="productForm.detailAddr" class="image-preview">
              <AsyncImage :image-key="productForm.detailAddr" style="width: 100%; height: 100%" />
            </div>
            <div v-else-if="detailFile" class="file-info">
              <img
                :src="getLocalFileUrl(detailFile)"
                style="width: 100%; height: 100%; object-fit: cover"
                alt="详情图预览"
              />
            </div>
            <div v-else class="upload-placeholder">
              <el-icon><Plus /></el-icon>
              <span>选择详情图</span>
            </div>
          </div>
        </div>
      </el-form-item>

      <!-- 规格部分 -->
      <el-form-item label="规格" prop="specification">
        <div class="specification-form">
          <div class="specification-inputs">
            <el-input
              v-model="newSpecification.item"
              placeholder="规格项（如：颜色）"
              size="small"
              style="width: 40%; margin-right: 10px"
            />
            <el-input
              v-model="newSpecification.value"
              placeholder="规格值（如：红色）"
              size="small"
              style="width: 40%; margin-right: 10px"
            />
            <el-button type="primary" size="small" @click="addSpecification"> 添加 </el-button>
          </div>

          <el-table
            :data="productForm.specificationList"
            style="width: 100%; margin-top: 10px"
            empty-text="暂无规格数据"
          >
            <el-table-column prop="item" label="规格项" />
            <el-table-column prop="value" label="规格值" />
            <el-table-column label="操作" width="80">
              <template #default="scope">
                <el-button type="danger" size="small" @click="removeSpecification(scope.$index)">
                  删除
                </el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-form-item>
    </el-form>

    <template #footer>
      <span class="dialog-footer">
        <el-button @click="handleCancel">取消</el-button>
        <el-button type="primary" @click="submitForm"> 提交 </el-button>
      </span>
    </template>
  </el-dialog>
</template>

<style scoped>
.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

.file-upload-container {
  position: relative;
  width: 148px;
  height: 148px;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  transition: border-color 0.3s;
}

.file-upload-container:hover {
  border-color: #409eff;
}

.file-input {
  position: absolute;
  width: 100%;
  height: 100%;
  opacity: 0;
  cursor: pointer;
}

.file-upload-display {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: #606266;
  background-color: #fafafa;
}

.upload-placeholder .el-icon {
  font-size: 28px;
  margin-bottom: 8px;
}

.file-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 10px;
  text-align: center;
  word-break: break-all;
  font-size: 12px;
  color: #606266;
}

.file-info .el-icon {
  font-size: 24px;
  margin-bottom: 5px;
}

.image-preview {
  width: 100%;
  height: 100%;
}
</style>
